
package com.ltu.payment.util;

import java.io.StringReader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import net.sf.json.JSONObject;



/**
 * 
 *  签名用的工具箱    
 */
public class SignUtils {

    /** 
     * 验证返回参数
     * @param params
     * @param key
     * @return
     */
    public static boolean checkParam(Map<String,String> params,String key){
        boolean result = false;
        if(params.containsKey("sign")){
            String sign = params.get("sign");
            params.remove("sign");
            StringBuilder buf = new StringBuilder((params.size() +1) * 10);
            SignUtils.buildPayParams(buf,params,false);
            String preStr = buf.toString();
            String signRecieve = MD5.sign(preStr,key, "utf-8");
            result = sign.equalsIgnoreCase(signRecieve);
        }
        return result;
    } 
    /**
     * 过滤参数
     * @author  
     * @param sArray
     * @return
     */
    public static Map<String, String> paraFilter(Map<String, String> sArray) {
        Map<String, String> result = new HashMap<String, String>(sArray.size());
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            String value = sArray.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")) {
                continue;
            }
            result.put(key, value);
        }
        return result;
    }
    /**
     * 过滤参数
     * @author  
     * @param sArray
     * @return
     */
    public static Map<String, Object> paraFilterObject(Map<String, Object> sArray) {
        Map<String, Object> result = new HashMap(sArray.size());
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            Object value = sArray.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")) {
                continue;
            }
            result.put(key, value);
        }
        return result;
    }
    
    /** 
     * 将map转成String
     * @param payParams
     * @return
     */
    public static String payParamsToString(Map<String, String> payParams){
        return payParamsToString(payParams,false);
    }
    
    public static String payParamsToString(Map<String, String> payParams,boolean encoding){
        return payParamsToString(new StringBuilder(),payParams,encoding);
    }
    
    /**
     * @author 
     * @param payParams
     * @return
     */
    public static String payParamsToString(StringBuilder sb,Map<String, String> payParams,boolean encoding){
        buildPayParams(sb,payParams,encoding);
        return sb.toString();
    }
    
    /**
     * @date 2019年10月14日
     * @author 若尘
     * @Description 生成微信支付签名用到的QueryString字符串
     * @param sb
     * @param payParams
     * @param encoding 是否编码
     * void
     */
    public static void buildPayParams(StringBuilder sb,Map<String, String> payParams,boolean encoding){
        List<String> keys = new ArrayList<String>(payParams.keySet());
        Collections.sort(keys);
        for(String key : keys){
            sb.append(key).append("=");
            if(encoding){
                sb.append(urlEncode(payParams.get(key)));
            }else{
                sb.append(payParams.get(key));
            }
            sb.append("&");
        }
        sb.setLength(sb.length() - 1);
    }
    public static void buildPayParamsObject(StringBuilder sb,Map<String, Object> payParams,boolean encoding){
        List<String> keys = new ArrayList<String>(payParams.keySet());
        Collections.sort(keys);
        for(String key : keys){
            sb.append(key).append("=");
            if(encoding){
                sb.append(urlEncode(payParams.get(key).toString()));
            }else{
                sb.append(payParams.get(key));
            }
            sb.append("&");
        }
        sb.setLength(sb.length() - 1);
    }
    
    public static String urlEncode(String str){
        try {
            return URLEncoder.encode(str, "UTF-8");
        } catch (Throwable e) {
            return str;
        } 
    }
    
    
    public static Element readerXml(String body,String encode) throws DocumentException {
        SAXReader reader = new SAXReader(false);
        InputSource source = new InputSource(new StringReader(body));
        source.setEncoding(encode);
        Document doc = reader.read(source);
        Element element = doc.getRootElement();
        return element;
    }
    
    
    /**
     * 功能：兴业支付-小程序支付参数
     * @param params
     * @return
     */
    public static Map<String, Object> getAppParam(Map<String,String> params){
        Map<String, Object> map=new HashMap<>();
        if(params.containsKey("pay_info")){
            String pay_info = params.get("pay_info");
            JSONObject jsonObject = JSONObject.fromObject(pay_info);
            Object appId=jsonObject.get("appId");
            Object timeStamp=jsonObject.get("timeStamp");
            Object nonceStr=jsonObject.get("nonceStr");
            Object packagez=jsonObject.get("package");
            Object signType=jsonObject.get("signType");
            Object paySign=jsonObject.get("paySign");
            map.put("appId",appId );
            map.put("timeStamp",timeStamp );
            map.put("nonceStr", nonceStr);
            map.put("package", packagez);
            map.put("signType",signType );
            map.put("paySign",paySign );
        }
        return map;
    }
    
    /**
     * 返回给前端的拉起收银台的数据
     * @param appId 小程序appid
     * @param timeStamp 时间戳
     * @param nonceStr 随机字符串
     * @param prepay_id 预支付凭证
     * @param payKey 支付密匙
     * @return
     */
    public static com.alibaba.fastjson.JSONObject createPayParams(String appId,String timeStamp,String nonceStr,String prepay_id,String payKey){
    	com.alibaba.fastjson.JSONObject map=new com.alibaba.fastjson.JSONObject();
        map.put("appId",appId );
        map.put("timeStamp",timeStamp );
        map.put("nonceStr", nonceStr);
        map.put("package", "prepay_id="+prepay_id);
        map.put("signType","MD5");
        String paySign = getPaySign(appId, timeStamp, nonceStr, prepay_id, payKey);
        map.put("paySign",paySign);
        return map;
    }
    
    /**
	 * 返回给前端的微信App支付签名
	 * @return
	 */
    public static void getSignByWxApp(com.alibaba.fastjson.JSONObject json,String payKey) {
    	StringBuilder   signSB=new StringBuilder();
    	String key="&key="+payKey;
    	String[] arr=new String[json.keySet().size()];
    	json.keySet().toArray(arr);
    	int len=arr.length;
    	Arrays.sort(arr);//QueryString排序 
    	for(int i=0;i<len;i++) {
    	 signSB.append(arr[i]);
    	 signSB.append("=");
    	 signSB.append(json.get(arr[i]));
    	 if(i<len-1)
    		 signSB.append("&");
    	}
    	signSB.append(key);  
    	System.out.println("\n 等待加密的字符串：" + signSB);
    	String sign = DigestUtils.md5Hex(signSB.toString()).toUpperCase();
    	json.put("sign", sign);
    }

    /**
     * 小程序拉起支付专用签名
     * 功能：根据prepay_id获取paySign
     * @param appId 小程序appid
     * @param timeStamp 时间戳
     * @param nonceStr 随机字符串
     * @param prepay_id 预支付凭证
     * @param payKey 支付密匙
     * @return
     */
	public static String getPaySign(String appId,String timeStamp,String nonceStr,String prepay_id,String payKey){
		String paySignTemp = "appId=" + appId + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id+ "&signType=MD5&timeStamp=" + timeStamp;
		String paySign = MD5.sign(paySignTemp,payKey,"utf-8");
        return paySign;  
    }
	

	/**
	 * 功能：退款签名
	 * @param appId
	 * @param timeStamp
	 * @param nonceStr
	 * @param payKey
	 * @return
	 */
	public static String getSign(String appId,String timeStamp,String nonceStr,String payKey){
		String paySignTemp = "appId=" + appId + "&nonceStr=" + nonceStr + "&signType=MD5&timeStamp=" + timeStamp;
		String paySign = MD5.sign(paySignTemp,payKey,"utf-8");
        return paySign;  
    } 
}

